package top.jiangqiang.qianyi.common.web;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import top.jiangqiang.qianyi.common.auth.interceptor.AdminTokenAuthInterceptor;
import top.jiangqiang.qianyi.common.auth.interceptor.WebsiteTokenAuthInterceptor;
import top.jiangqiang.qianyi.common.constants.GlobalConstants;
import top.jiangqiang.qianyi.common.constants.http.Error500Status;
import top.jiangqiang.qianyi.common.exception.Error500Exception;
import top.jiangqiang.qianyi.common.properties.AuthProperties;
import top.jiangqiang.qianyi.common.properties.FileProperties;

import java.util.*;

@Slf4j
@RequiredArgsConstructor
@ConditionalOnClass(WebMvcConfigurer.class)
@Configuration
public class QianYiWebMvcConfigurer implements WebMvcConfigurer {
    private final AuthProperties authProperties;
    private final FileProperties fileProperties;
    private final AdminTokenAuthInterceptor adminTokenAuthInterceptor;
    private final WebsiteTokenAuthInterceptor websiteTokenAuthInterceptor;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        Map<String, String> staticResourceMapping = fileProperties.getStaticResourceMapping();
        if (CollUtil.isNotEmpty(staticResourceMapping)) {
            //path：访问路径 resourceLocationStr：一个或多个资源位置通过逗号拼接的字符串
            staticResourceMapping.forEach((path, resourceLocationStr) -> {
                String[] resourceLocations = Arrays.stream(resourceLocationStr.split(",")).filter(StrUtil::isNotBlank).map(resourceLocation -> {
                    resourceLocation = resourceLocation.trim();
                    if (resourceLocation.startsWith("file:") || resourceLocation.startsWith("classpath:")) {
                        return resourceLocation;
                    } else {
                        return "file:" + resourceLocation;
                    }
                }).toArray(String[]::new);
                registry.addResourceHandler(path.replaceAll("//", "/")).addResourceLocations(resourceLocations);
            });
        }
    }

    /**
     * sa-token拦截器不会拦截静态资源
     * 注册路由拦截器，自定义认证规则
     *
     * @param registry InterceptorRegistry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //所有支持匿名访问的接口
        List<String> allowAnonymousAccess = CollUtil.defaultIfEmpty(authProperties.getAllowAnonymousAccess(), new ArrayList<>());
        //静态资源访问路径也需要匿名访问
        allowAnonymousAccess.addAll(MapUtil.defaultIfEmpty(fileProperties.getStaticResourceMapping(), new HashMap<>()).keySet());
        if (allowAnonymousAccess.contains("/**")) {
            log.error("不允许全部匿名访问");
            //不允许全部匿名
            throw new Error500Exception(Error500Status.INTERNAL_SERVER_ERROR);
        }
        //解析token，获取对应的用户信息
        registry.addInterceptor(adminTokenAuthInterceptor).addPathPatterns(GlobalConstants.AdminRequestURLConstants.ADMIN_CONTROLLER_PATTERN).excludePathPatterns(allowAnonymousAccess);
        registry.addInterceptor(websiteTokenAuthInterceptor).addPathPatterns(GlobalConstants.WebsiteRequestURLConstants.WEBSITE_CONTROLLER_PATTERN).excludePathPatterns(allowAnonymousAccess);
    }
}
